<template>
  <div class="home-container">
    <!-- 头部区域 -->
    <van-nav-bar fixed>
      <template #left>
        <img src="../../assets/logo.png" alt="" class="logo">
      </template>
      <template #right>
        <!-- van-icon 是 Vant 提供的图标组件 -->
        <!-- name 属性用来指定渲染哪个图标, size 用来指定图标的大小 -->
        <van-icon name="search" size="18" @click="$router.push('/search')" />
      </template>
    </van-nav-bar>

    <!-- 频道列表区域 -->
    <van-tabs sticky offset-top="1.22667rem" v-model="active" @change="onTabChange">
      <van-tab :title="item.name" v-for="item in channels" :key="item.id">
        <!-- 实现下拉刷新的功能 -->
        <van-pull-refresh v-model="isLoading" @refresh="onRefresh">
          <!-- 实现上拉加载更多 -->
          <van-list v-model="loading" :finished="finished" finished-text="没有更多了" @load="onLoad">
            <!-- 文章的列表区域 -->
            <!-- vue 官方推荐：使用短横线的方式，使用自定义的组件 -->
            <article-list :list="articleList"></article-list>
          </van-list>
        </van-pull-refresh>
      </van-tab>
    </van-tabs>

    <!-- 右侧的编辑频道的小图标 -->
    <van-icon name="plus" size="14" class="moreChannels" @click="show = true" />

    <!-- 弹出层组件 -->
    <!-- close-on-click-overlay 是否在点击遮罩层后关闭（false 不关闭） -->
    <van-popup v-model="show" :close-on-click-overlay="false" @closed="onPopupClosed">
      <div class="popup-container">

        <!-- 弹出层的头部区域 -->
        <van-nav-bar title="频道管理">
          <template #right>
            <van-icon name="cross" size="14" color="white" @click="show = false" />
          </template>
        </van-nav-bar>

        <!-- 弹出层的主体区域 -->
        <div class="pop-body">
          <!-- 我的频道 -->
          <div class="my-channel-box">
            <div class="channel-title">
              <span>我的频道：</span>
              <span @click="isEdit = !isEdit">{{isEdit ? '完成' : '编辑'}}</span>
            </div>
            <!-- 我的频道列表 -->
            <van-row type="flex">
              <van-col span="6" v-for="(item, index) in channels" :key="item.id">
                <!-- 每个频道的 Item 项 -->
                <div class="channel-item van-hairline--surround" @click="removeChannel(item.id, index)">
                  {{item.name}}
                  <!-- 删除的徽标 -->
                  <van-badge color="transparent" class="cross-badge" v-if="isEdit && item.id !== 0">
                    <template #content>
                      <van-icon name="cross" class="badge-icon" color="#cfcfcf" size="12" />
                    </template>
                  </van-badge>
                </div>
              </van-col>
            </van-row>
          </div>

          <!-- 更多频道 -->
          <div class="more-channel-box">
            <div class="channel-title">
              <span>点击添加更多频道：</span>
            </div>
            <!-- 更多频道列表 -->
            <van-row type="flex">
              <van-col span="6" v-for="item in moreChannels" :key="item.id">
                <div class="channel-item van-hairline--surround" @click="addChannel(item)">{{item.name}}</div>
              </van-col>
            </van-row>
          </div>
        </div>
      </div>
    </van-popup>

  </div>
</template>

<script>
// 按需导入需要的 API 方法
import {
  getUserChannels,
  getArticlesById,
  getAllChannels,
  updateUserChannels
} from '@/api/homeAPI'

// 导入文章列表组件
import ArticleList from './ArticleList.vue'

export default {
  name: 'Home',
  data() {
    return {
      // 已关注的频道列表数据
      channels: [],
      // 激活的标签页的索引
      active: 0,
      // 文章列表的数据
      articleList: [],
      // 是否正在请求上拉加载更多的数据
      loading: false,
      // 所有数据是否都加载完毕了
      finished: false,
      // 是否正在请求下拉刷新的数据
      isLoading: false,
      // 是否展示编辑频道的弹出层
      show: false,
      // 所有的频道列表
      allChannels: [],
      // 是否处于编辑状态
      isEdit: false
    }
  },
  created() {
    // 预调用 getChannels 获取用户的频道列表数据
    this.getChannels()
    // 获取文章列表的数据
    // 由于每个用户，都有推荐这么频道，因此上来就请求【推荐】频道下的文章列表数据，推荐这个频道的 Id 是 0
    // this.getArticleList(0)
    this.getAllChannel()
  },
  methods: {
    // 获取用户频道数据的方法
    async getChannels() {
      // 请求频道数据
      const { data: res } = await getUserChannels()
      if (res.message === 'OK') {
        // 把数据存储到 channels 中
        this.channels = res.data.channels
      }
    },
    // 获取文章列表的数据
    // isRefresh 是布尔值，true 表示下拉刷新；false 表示上拉加载更多
    async getArticleList(id, isRefresh) {
      const { data: res } = await getArticlesById({
        channel_id: id,
        timestamp: Date.now(),
        with_top: 1
      })

      if (res.message === 'OK') {
        // 不要再用 = 进行覆盖了，而是要用旧数据拼接上新数据
        // this.articleList = res.data.results
        if (isRefresh) {
          // 下拉刷新
          // 新的在前，旧的在后
          this.articleList = res.data.results.concat(this.articleList)
        } else {
          // 上拉加载更多
          // 旧的在前，新的在后
          this.articleList = this.articleList.concat(res.data.results)
        }

        // 目的：告诉 List 组件，数据请求回来了，可以触发下次的触底操作了
        this.loading = false
        this.isLoading = false
        // 当数据请求成功之后，要判断是否没有数据了，如果没有了，就把 finished 改为 true。
        if (res.data.results.length === 0) {
          this.finished = true
        }
      }
    },
    // 加载下一页数据的方法
    onLoad() {
      // 注意：当执行到 onLoad 函数的时候，this.channels 数组可能为空，因此，需要进行三元表达式的判断
      const id = this.channels.length === 0 ? 0 : this.channels[this.active].id
      // 发起请求，请求下一页数据
      this.getArticleList(id)
    },
    // 频道的选中项发生了变化
    onTabChange(index) {
      // 清除旧文章列表数据
      this.articleList = []
      // 重置 loading 和 finished
      this.loading = false
      this.finished = false

      const id = this.channels[index].id
      this.getArticleList(id)
    },
    // 触发了下拉刷新
    onRefresh() {
      // 获取到频道的 Id
      const id = this.channels[this.active].id
      // TODO：请求下拉刷新的数据
      this.getArticleList(id, true)
    },
    // 获取所有的频道列表数据
    async getAllChannel() {
      // 把方向键附近的 PgUp 改键为 Home；把 PgDn 改键为 End.
      const { data: res } = await getAllChannels()
      if (res.message === 'OK') {
        this.allChannels = res.data.channels
      }
    },
    // 添加新频道
    addChannel(item) {
      this.channels.push(item)
      // 调用接口，把数据存储到服务器
      this.updateChannels()
    },
    // 把更新后的频道列表数据，保存到服务器
    async updateChannels() {
      // 1. 准备数据
      const arr = this.channels
        .filter((x) => x.name !== '推荐')
        .map((x, i) => {
          return {
            id: x.id, // 频道的 Id
            seq: i + 1 // 频道的排序序号
          }
        })
      // 把要发送的数据准备好了
      const data = { channels: arr }
      // 2. 调用接口，发送数据
      const { data: res } = await updateUserChannels(data)
      if (res.message === 'OK') {
        // this 是组件的实例
        // 注意：其实每一个 .vue 组件本质上都是 Vue 构造函数的实例对象
        this.$notify({ type: 'success', message: '更新成功', duration: 1000 })
      }
    },
    // 根据 id 移除关注的频道
    removeChannel(id, index) {
      if (this.isEdit) {
        // 编辑状态
        this.channels = this.channels.filter((x) => x.id !== id)
        // TODO：把最新的频道列表数据，保存到服务器
        this.updateChannels()
      } else {
        // 非编辑状态
        // 1. 把点击项的索引，赋值给 tabs 的 active
        this.active = index
        // 2. 同时，关闭 popup 弹出层
        this.show = false
        // 3. 重新发起数据请求
        this.articleList = []
        this.isLoading = false
        this.finished = false
        this.loading = false
        this.getArticleList(id)
      }
    },
    // 监听 Popup 完全关闭的事件
    onPopupClosed() {
      this.isEdit = false
    }
  },
  computed: {
    // 动态计算未关注的频道列表数据
    moreChannels() {
      // 1. 循环所有的频道
      // 2. 判断当前的循环项，是否在已关注的频道列表之中
      // 3. 如果不在已关注的频道列表中，则把当前循环项过滤出来，最终形成一个新数组，返回即可
      return this.allChannels.filter((x) => {
        const index = this.channels.findIndex((y) => y.id === x.id)
        if (index === -1) return true
      })
    }
  },
  // 注册组件
  components: {
    ArticleList
  }
}
</script>

<style lang="less" scoped>
.home-container {
  padding-top: 46px;

  .logo {
    height: 80%;
  }
}

// 设置 tabs 容器的样式
/deep/ .van-tabs__wrap {
  padding-right: 30px;
  background-color: #fff;
}

// 设置小图标的样式
.moreChannels {
  position: fixed;
  top: 62px;
  right: 8px;
  z-index: 999;
}

.van-popup,
.popup-container {
  background-color: transparent;
  height: 100%;
  width: 100%;
}

.popup-container {
  display: flex;
  flex-direction: column;
}

.pop-header {
  height: 90px;
  background-color: #007bff;
  color: white;
  text-align: center;
  font-size: 14px;
  position: relative;
  .title {
    width: 100%;
    position: absolute;
    bottom: 15px;
  }
}

.pop-body {
  flex: 1;
  overflow: scroll;
  padding: 8px;
  background-color: white;
}

.my-channel-box,
.more-channel-box {
  .channel-title {
    display: flex;
    justify-content: space-between;
    font-size: 14px;
    line-height: 28px;
    padding: 0 6px;
  }
}

.channel-item {
  font-size: 12px;
  text-align: center;
  line-height: 36px;
  background-color: #fafafa;
  margin: 5px;
}

.cross-badge {
  position: absolute;
  right: -3px;
  top: 0;
  border: none;
}
</style>
